import os
import threading
from time import sleep

from PyQt5.QtCore import pyqtSignal, Qt, QObject

from AdbUtils import adb_execute_shell


class MonitorInfo(QObject):
    def __init__(self, method):
        super().__init__()
        self.method = method

    def work(self):
        self.method()


class MonitorTop(MonitorInfo):
    signal = pyqtSignal()
    lock = threading.Lock()
    allDict = {}

    def __init__(self, callback):
        super(MonitorTop, self).__init__(self.adb_top)
        self.signal.connect(self.refreshPg, Qt.QueuedConnection)
        self.callback = callback

    def adb_top(self):
        cmd = "top -n 1"
        ret, msg = adb_execute_shell(cmd)
        itemDict = self.parse_top(ret)
        if itemDict:
            with self.lock:
                if len(self.allDict) <= 0:
                    self.allDict = itemDict
                else:
                    for proc in itemDict.keys():
                        if proc in self.allDict.keys():
                            old = self.allDict[proc]
                            for oldKey in old.keys():
                                self.allDict[proc][oldKey].extend(itemDict[proc][oldKey])
                        else:
                            self.allDict[proc] = itemDict[proc]

            self.signal.emit()
            # print("allDict", self.allDict)

    def parse_top(self, info):
        if info:
            infos = info.split(os.linesep)
            index_cpu = -1
            index_rss = -1
            index_proc = -1
            index_user = -1
            itemDict = {}
            for tmp in infos:
                if tmp.strip().startswith("PID"):
                    items = tmp.split()
                    for i in range(len(items)):
                        if items[i].strip() == "CPU%":
                            index_cpu = i
                        elif items[i].strip() == "RSS":
                            index_rss = i
                        elif items[i].strip() == "Name":
                            index_proc = i
                        elif items[i].strip() == "USER":
                            index_user = i
                elif index_cpu != -1:
                    items = tmp.split()
                    if len(items) <= 0:
                        continue

                    user = items[index_user].strip()
                    if user in ["root"]:
                        continue

                    rss = items[index_rss].strip()
                    cpu = items[index_cpu].strip()
                    if len(items) > index_proc:
                        proc = items[index_proc].strip()
                    else:
                        proc = ""
                    itemDict[proc] = {"rss": [int(rss[:-1])], "cpu": [int(cpu[:-1])]}

            # print(itemDict)
            return itemDict
        return None

    def refreshPg(self):
        with self.lock:
            self.callback(self.allDict)


class Monitor(threading.Thread):

    def __init__(self, ):
        threading.Thread.__init__(self)
        self.condition = threading.Condition()
        self.MonitorList = []
        self.exitFlag = False

    def addMonitor(self, m_info):
        with self.condition:
            if m_info not in self.MonitorList:
                self.MonitorList.append(m_info)
                self.condition.notifyAll()

    def removeMonitor(self, m_info):
        with self.condition:
            self.MonitorList.remove(m_info)

    def setExitFlag(self):
        with self.condition:
            self.MonitorList.clear()
            self.exitFlag = True
            self.condition.notifyAll()

    def run(self):
        while not self.exitFlag:
            with self.condition:
                if len(self.MonitorList) <= 0:
                    self.condition.wait()

                for m_info in self.MonitorList:
                    m_info.work()
            sleep(1)
